#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include<openssl/bn.h>
#include <openssl/rsa.h>
#include<openssl/pem.h>

extern "C"
{
#include <applink.c>
};

void PrintHex(unsigned char* strBuff, int len)
{
    for (int i = 0; i < len; i++)
    {
        printf("%02x", strBuff[i]);
    }
    puts("");
}

#define STRING_PRIVATE_KEY_PATH     ".//PrivateKey.txt"
#define STRING_PUBLIC_KEY_PATH      ".//PublicKey.txt"

void RsaTest()  //  密钥生成
{
    RSA* lpRsa;
    FILE* lpPrivKeyFile;
    FILE* lpPubKeyFile;
    lpPrivKeyFile = fopen(STRING_PRIVATE_KEY_PATH, "w");
    if (!lpPrivKeyFile) return;

    lpRsa = RSA_generate_key(1024, RSA_F4, NULL, NULL);
    //printf("BIGNUM: %s\n", BN_bn2hex(RSA_get0_n(lpRsa)));
    PEM_write_RSAPrivateKey(lpPrivKeyFile, lpRsa, NULL, NULL, 0, NULL, NULL);
    fclose(lpPrivKeyFile);

    unsigned char* lpRsaN = (unsigned char*)calloc(RSA_size(lpRsa), sizeof(unsigned char));
    unsigned char* lpRsaE = (unsigned char*)calloc(RSA_size(lpRsa), sizeof(unsigned char));

    int SizeOfRsaN = BN_bn2bin(RSA_get0_n(lpRsa), lpRsaN);
    int SizeOfRsaE = BN_bn2bin(RSA_get0_e(lpRsa), lpRsaE);

    RSA* lpRsa2 = RSA_new();
    RSA_set0_key(lpRsa2, BN_bin2bn(lpRsaN, SizeOfRsaN, NULL), BN_bin2bn(lpRsaE, SizeOfRsaE, NULL), NULL);

    lpPubKeyFile = fopen(STRING_PUBLIC_KEY_PATH, "w");
    if (!lpPubKeyFile) return;
    PEM_write_RSAPublicKey(lpPubKeyFile, lpRsa2);
    fclose(lpPubKeyFile);

    RSA_free(lpRsa);
    RSA_free(lpRsa2);
}

void RsaTest2()     //  加密解密
{
    RSA* lpRsa;
    RSA* lpRsa2;
    FILE* lpPrivKeyFile;
    FILE* lpPubKeyFile;
    int nRsaLen;
    unsigned char strBuff[16] = { 0 };
    unsigned char strCipherText[1024] = { 0 };
    unsigned char strPlainText[1024] = { 0 };
    int nRet;

    //
    //  加密
    //

    strcpy((char*)strBuff, "Hello Rsa");
    lpPubKeyFile = fopen(STRING_PUBLIC_KEY_PATH, "r");
    if (!lpPubKeyFile) return;

    lpRsa = PEM_read_RSAPublicKey(lpPubKeyFile, NULL, NULL, NULL);
    fclose(lpPubKeyFile);
    if (!lpRsa) return;

    nRsaLen = RSA_size(lpRsa);
    nRet = RSA_public_encrypt(nRsaLen, strBuff, strCipherText, lpRsa, RSA_NO_PADDING);
    if (!nRet) return;
    PrintHex(strCipherText, strlen((char*)strCipherText));
    RSA_free(lpRsa);

    //
    //  解密
    //

    lpPrivKeyFile = fopen(STRING_PRIVATE_KEY_PATH, "r");
    if (!lpPrivKeyFile) return;

    lpRsa2 = PEM_read_RSAPrivateKey(lpPrivKeyFile, NULL, NULL, NULL);
    fclose(lpPrivKeyFile);
    if (!lpRsa2) return;

    nRsaLen = RSA_size(lpRsa2);
    nRet = RSA_private_decrypt(nRsaLen, strCipherText, strPlainText, lpRsa2, RSA_NO_PADDING);
    if (!nRet) return;
    PrintHex(strPlainText, strlen((char*)strPlainText));
    printf("%s\r\n", strPlainText);
    RSA_free(lpRsa2);
}

int main()
{
    RsaTest();
    RsaTest2();
    return 0;
}